﻿using System;
using System.Collections.Generic;
using System.Text;

namespace AdaptiveAgents.Loggers
{
    /// <summary>
    /// Different types of messages to be logged
    /// </summary>
    public enum MessageType {
        System,
        HackMessage,
        GameDetails, 
        Turn, //End of game round
        EpsilonGraph, //To find the best epsilon
        EstimatedCompetence, //Estimated competence of an agent
        PlayersCount, //Indication of the number of the players
        NextPerformer, //Next agent to act was set 
        NextPerformerChoice, //Choosing next performer
        GameStats, //Statistics of game
        OtherAgentCompetence, //Agent knows about competence of other agent
        OtherAgentMaxCompetence, //Agent know about max competence ot other agent
        ObservationsHeader, //Report about Agent observation
        ObservationsSoFar, //Report the number of observations by an agent so far
        ObservationPrint, //Print an observation by an agent
        AgentTied, //There is a tie while choosing agents
        EstimatedEpsilon, //Estimated epsilon of an agent
        AgentActingAsExpected, //Agent is acting as expected
        Performence, //Report about Agent performence
        NumActions, //Num of actions of agent
        AgentAttributes, //Print the attributes of an agent
        HowChoosingNextPlayer, //The way of choosing the next player
        SummerizeGameResults, //Summerize the run of multiple games
        TypeOfGame, //Current the of game
        LineSeperator, //Mark of a seperator between sections
        NewLine //New line feed
    }

    /// <summary>
    /// Abstract logger 
    /// </summary>
    public abstract class Logger 
    {
        /// <summary>
        /// Writes message according to its type and provided data
        /// </summary>
        /// <param name="message">message type</param>
        /// <param name="p">array of data objects to be written</param>
        public void Write(MessageType message, params Object[] p)
        {
            writeInternal(message, false, p);
        }

        /// <summary>
        /// Abstract method for writing a message accroding to different types and data.
        /// </summary>
        /// <param name="message">message type</param>
        /// <param name="newLine">indication of writing a new line character after current message</param>
        /// <param name="p">array of data objects to be written</param>
        protected abstract void writeInternal(MessageType message, bool newLine, params Object[] p);

        /// <summary>
        /// Writes message according to its type and provided data and afterwards prints a new line
        /// </summary>
        /// <param name="message">message type</param>
        /// <param name="p">array of data objects to be written</param>
        public void WriteLine(MessageType message, params Object[] p)
        {
            writeInternal(message, true, p);
        }

        /// <summary>
        /// Abstract method for closing the logger data stream
        /// </summary>
        public abstract void Close();

    }
}
